package com.atguigu.gulimall.product;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.web.bind.annotation.ControllerAdvice;


/**
 * 1、整合Mabits-Plus
 *  1）、导入依赖
 *  <dependency>
 *             <groupId>com.baomidou</groupId>
 *             <artifactId>mybatis-plus-boot-starter</artifactId>
 *             <version>3.2.0</version>
 *  </dependency>
 *  2)、配置
 *      1、配置上数据源
 *          1）、导入数据库驱动
 *          2）、再application.yml中配置数据源相关信息
 *      2、配置mybatis-plus
 *          1）、使用@MapperScan
 *          2）、告诉MyBatis-Plus,sql映射文件位置
 * 2、逻辑删除
 *  1）、配置全局逻辑删除规则，在application.yml文件中添加
 *          mybatis-plus:
 *             global-config:
 *                 db-config:
 *                     logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
 *                     logic-delete-value: 1 # 逻辑已删除值(默认为 1)
 *                     logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
 *  2）、配置逻辑删除的组件Bean（mybatis-plus 3.1.1之后不需要）
 *  3）、给实体类上需要删除的字段加注 @TableLogic
 *      例如：在CategoryEntity类中
 *          @TableLogic
 *          private Integer showStatus;
 * 3、JSR303后端校验
 *  1）、给Bean添加校验注解: javax.validation.constraints参考该包中的注解功能
 *  2）、在controller中对应的功能处标注@Valid，开启校验功能
 *         效果：校验错误以后会有默认的响应；
 *  3）、给校验的bean后紧跟一个BindingResult result就可以获取到娇艳的结果
 *      可以自定义封装错误
 *  4）、分组校验（多场景的复杂校验）
 *      1、给注解标注什么情况需要进行校验，在common中写空的分组接口作为分组标识
 *          @Null(message = "新增不能指定id",groups = {AddGroup.class})
 *      2、将@Valid换为@Validated({AddGroup.class})并配置好分组
 *      3、默认没有指定分组的校验注解@NotBlank，在分组校验情况下不生效，只会在@Validated后不加分组的方法中生效
 *  5）、自定义校验
 *      1、编写一个自定义的校验注解 ListValue
 *      2、编写一个自定义的校验器 ConstraintValidator(见common的valid)
 *      3、关联自定义的校验器和自定义的校验注解
 * @Documented
 * @Constraint(validatedBy = {ListValueConstraintValidator.class【可以指定多个不同校验器，适配不同类型的校验】})
 * @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
 * @Retention(RetentionPolicy.RUNTIME)
 * public @interface ListValue {
 *
 * 4、统一处理异常
 *  @ControllerAdvice
 *      1）、编写异常类处理，使用@ControllerAdvice。
 *      2）、使用@ExceptionHandler标注方法可以处理的异常
 *
 * 使用阿里云oss做品牌管理的文件管理：
 * 1、引入对象存储的oss-stater
 * <!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alicloud-oss -->
 * <dependency>
 *     <groupId>com.alibaba.cloud</groupId>
 *     <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
 *     <version>2.2.0.RELEASE</version>
 * </dependency>
 * 2、配置key、endpoint相关信息到application.yml文件中
 * 3、使用对象存储的OSSClient进行相关操作
 * 参考test中的代码和官方文档
 * https://github.com/alibaba/aliyun-spring-boot/blob/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample/README-zh.md
 *
 * 5、模板引擎
 *  1）、thymeleaf-starter:关闭缓存
 *  2）、静态资源都放在static文件夹下就可以按照路径直接访问
 *  3）、页面放在templates下，直接访问
 *      springboot，访问项目的时候，默认会找index
 *  4）、页面修改不重启服务器实时更新
 *      1、引入dev-tools
 *      2、修改完页面使用快捷键Ctrl+Shift+F9重新编译当前文件
 *      3、刷新页面（需要将 thymeleaf: cache: false themleaf的缓存关闭）
 *      注：如果修改了代码的配置，建议重启项目
 * 6、整合Redis
 *  1）、引入依赖spring-boot-starter-data-redis
 *  2）、在application.yml中简单配置redis的host等信息
 *  3）、使用SpringBoot自动配置好的StringRedisTemplate来操作redis
 * 7、整合redisson作为分布式锁等功能框架
 *  1）、引入依赖
 *  <!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
         * <dependency>
         *     <groupId>org.redisson</groupId>
         *     <artifactId>redisson</artifactId>
         *     <version>3.12.0</version>
         * </dependency>
 *  2）、配置redisson
 *      MyRedissonConfig给容器中配置一个RedissonClient实例即可
 *  3）、使用
 *      参照文档做。https://redis.io/
 * 8、整合SpringCache简化缓存开发
 *  1）、引入依赖
 *          <dependency>
 *             <groupId>org.springframework.boot</groupId>
 *             <artifactId>spring-boot-starter-cache</artifactId>
 *         </dependency>
 *                 <dependency>
 *             <groupId>org.springframework.boot</groupId>
 *             <artifactId>spring-boot-starter-data-redis</artifactId>
 *             <exclusions>
 *                 <exclusion>
 *                     <groupId>io.lettuce</groupId>
 *                     <artifactId>lettuce-core</artifactId>
 *                 </exclusion>
 *             </exclusions>
 *         </dependency>
 *         <dependency>
 *             <groupId>redis.clients</groupId>
 *             <artifactId>jedis</artifactId>
 *         </dependency>
 * 2）、写配置
 *      （1）、自动配置了哪些：
 *          CacheAutoConfiguration会导入RedisCacheConfiguration；
 *          自动配好了缓存管理器RedisCacheManager
 *      （2）、手动配置：
 *          配置redis作为缓存
 * 3）、测试使用缓存：
 * @Cacheable: Triggers cache population.触发将数据保存到缓存
 * @CacheEvict: Triggers cache eviction.触发将数据从缓存删除
 * @CachePut: Updates the cache without interfering with the method execution.不影响方法执行的情况下更新缓存
 * @Caching: Regroups multiple cache operations to be applied on a method.组合以上多个操作
 * @CacheConfig: Shares some common cache-related settings at class-level.在类级别共享相同的缓存配置
 *  （1）、开启缓存功能：@EnableCaching
 *  （2）、只需要使用注解就能完成缓存
 * 4）、原理：
 *  CacheAutoConfiguration -> RedisCacheConfiguration -> 自动配置了RedisCacheManager ->
 *  初始化所有缓存 ->每个缓存决定使用什么配置 -> 如果redisCacheConfiguration有就用已有的，没有就用默认的配置 ->
 *  想改缓存的配置，只需要给容器中放一个RedisCacheConfiguration即可 -> 就会应用到当前RedisCacheManager管理的所有缓存分区中 ->
 *
 * */

//@MapperScan("com.atguigu.gulimall.product.dao")
@EnableCaching
@EnableFeignClients(basePackages = "com.atguigu.gulimall.product.feign")
@EnableDiscoveryClient
@MapperScan("com.atguigu.gulimall.product.dao")
@SpringBootApplication
public class GulimallProductApplication {

    public static void main(String[] args) {
        SpringApplication.run(GulimallProductApplication.class, args);
    }

}
